home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / info-service / www / src / midaswww-1.0 / custom.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-16  |  43.9 KB  |  1,503 lines

  1. #include <stdio.h>                              /* For printf and so on. */
  2. #include <string.h>
  3. #include <Mrm/MrmAppl.h>                        /* Motif Toolkit and MRM */
  4. #include <Xm/Text.h>
  5. #include <Xm/ToggleBG.h>
  6. #include <Xm/PushBG.h>
  7. #include <Xm/CascadeBG.h>
  8. #include <Xm/SeparatoG.h>
  9. #include <Xm/RowColumn.h>
  10. #include "midaslist.h"
  11. #include "midasoperand.h"
  12. #include "midasshell.h"
  13.  
  14. XmString MidasCharToString();
  15. MidasShell *MidasGetShell();
  16. Widget MidasFetch();
  17.  
  18. #ifndef VAX
  19. WidgetList DXmChildren();
  20. int DXmNumChildren();
  21. #endif
  22.  
  23. MidasOperand MidasGetAppResource();
  24.  
  25. struct VerbInMenu {
  26.     int     Verb;
  27.     int     Menu;
  28. };
  29.  
  30. typedef struct VerbInMenu VerbInMenu;
  31.  
  32. struct VerbStruct {
  33.     char *Command;
  34.     Boolean IsToggle;
  35. };
  36.     
  37. typedef struct VerbStruct VerbStruct; 
  38.  
  39. struct CustomHeader {
  40.     int    Modified;
  41.     int    Changed;
  42.     Widget Fetched;
  43.     Widget Parent;
  44.  
  45.     Widget CustomCommandText;
  46.     Widget CustomVerbAddButton;
  47.     Widget CustomVerbDeleteButton;
  48.     Widget CustomVerbList;
  49.     Widget CustomVerbText;
  50.     Widget CustomVerbIsToggle;
  51.     Widget CustomMenuAddButton;
  52.     Widget CustomMenuDeleteButton;
  53.     Widget CustomMenuList;
  54.     Widget CustomMenuText;
  55.     Widget CustomVMUpButton;
  56.     Widget CustomVMDownButton;
  57.     Widget CustomVMAddVerbButton;
  58.     Widget CustomVMAddMenuButton;
  59.     Widget CustomVMSeparatorButton;
  60.     Widget CustomVMRemoveButton;
  61.     Widget CustomVMList;
  62.     Widget CustomVMActiveLabel;
  63.     Widget CustomOKButton;
  64.     Widget CustomApplyButton;
  65.     Widget CustomCancelButton;
  66.     Widget CustomResetButton;
  67.     
  68.     List TempVerbList;
  69.     List TempMenuList;
  70.     List VerbList;
  71.     List MenuList;
  72.     List *VMList;
  73.     List ConnectList;
  74. };
  75.  
  76. typedef struct CustomHeader CustomHeader;
  77.  
  78. struct Link  {
  79.     Widget        Widget;
  80.     CustomHeader *Header;
  81. };
  82.  
  83. typedef struct Link Link;
  84.  
  85. static List CustomHeaders; 
  86. static int  ExitResponse; 
  87.  
  88. static void CustomSetActiveMenu(Header,Label)
  89.       CustomHeader *Header;
  90.       XmString Label;
  91. {
  92.     int n = 0;
  93.     Arg args[10];
  94.     XtSetArg(args[n],XmNlabelString,Label); n++;
  95.     XtSetValues(Header->CustomVMActiveLabel,args,n);
  96. }
  97. static char *CustomAppendArrow(name)
  98.     char *name;
  99. {
  100.     char *result;
  101.     result = strcpy(XtMalloc(strlen(name)+4),name);
  102.     return strcat(result," =>");
  103. }
  104. static Boolean CustomIsChild(Header,parent,child)
  105.       CustomHeader *Header;
  106.       List         *parent;
  107.       List         *child;
  108.  
  109. {
  110.     ListItem *i;
  111.  
  112.     for (i = parent->First; i != 0; i = i->Next)
  113.       {
  114.         VerbInMenu *vm = ((VerbInMenu *) i->Pointer);
  115.         if (vm->Menu != 0)
  116.           { 
  117.             ListItem *menu = MidasFindItemInListPos(&Header->TempMenuList,vm->Menu);
  118.             List *NewList = ((List *) menu->Pointer);
  119.             if (NewList = child) return 1;
  120.             else if (CustomIsChild(Header,NewList,child)) return 1;
  121.           }
  122.       }
  123.     return 0;
  124. }             
  125. static void CustomUpdatePositionsAdd(L,pos,verb)
  126.     List         *L;
  127.     int           pos;
  128.     int           verb;
  129. {
  130.     ListItem *i , *j;
  131.  
  132.     for (i = L->First; i != 0; i = i->Next)
  133.       {
  134.         List *menu = ((List *) i->Pointer); 
  135.         if (menu != 0)
  136.           for (j = menu->First; j != 0; j = j->Next)
  137.             {
  138.               VerbInMenu *vm = j->Pointer;
  139.               if (verb)
  140.                 {
  141.                   if (vm->Verb >= pos) vm->Verb += 1;
  142.                 }
  143.               else
  144.                 {
  145.                   if (vm->Menu >= pos) vm->Menu += 1;
  146.                 }
  147.             }
  148.         }
  149. };
  150. static void CustomUpdatePositionsRemove(L,pos,verb)
  151.     List         *L;
  152.     int           pos;
  153.     int           verb;
  154. {
  155.     ListItem *i, *j, *next;
  156.  
  157.     for (i = L->First; i != 0; i = i->Next)
  158.       {
  159.         List *menu = ((List *) i->Pointer); 
  160.         for (j = menu->First; j != 0; j = next)
  161.           {
  162.             VerbInMenu *vm = j->Pointer;
  163.             next = j->Next;
  164.             if (verb)
  165.               {
  166.                 if      (vm->Verb == pos) MidasRemoveItemFromList(menu,j);
  167.                 else if (vm->Verb >  pos) vm->Verb -= 1;
  168.               }
  169.             else
  170.               {
  171.                 if      (vm->Menu == pos) MidasRemoveItemFromList(menu,j);
  172.                 else if (vm->Menu >  pos) vm->Menu -= 1;
  173.               }
  174.           }
  175.       }
  176. };
  177. static void CustomUpdateSensitivity(Header) 
  178.                                       /*----Figures out which keys should be 
  179.                                             sensitive at the current time    */
  180.     CustomHeader *Header;
  181. {
  182.  
  183.     char *menu;
  184.     char *verb;
  185.     char *command;
  186.     Boolean sensitive;
  187.    
  188.     XtSetSensitive(Header->CustomApplyButton,Header->Changed != 0);
  189.     XtSetSensitive(Header->CustomResetButton,Header->Changed != 0);
  190.  
  191.     XtSetSensitive(Header->CustomVerbDeleteButton,
  192.                    Header->TempVerbList.Selected != 0);
  193.     XtSetSensitive(Header->CustomMenuDeleteButton,
  194.                    Header->TempMenuList.Selected != 0);
  195.  
  196.     verb    = XmTextGetString(Header->CustomVerbText);
  197.     command = XmTextGetString(Header->CustomCommandText);
  198.     sensitive = (strcmp(verb,"") != 0 && strcmp(command,"") != 0 );
  199.     XtSetSensitive(Header->CustomVerbAddButton,sensitive);
  200.     XtFree(command);
  201.     XtFree(verb);
  202.  
  203.     menu = XmTextGetString(Header->CustomMenuText);
  204.     sensitive = (strcmp(menu,"")!=0);
  205.     XtSetSensitive(Header->CustomMenuAddButton,sensitive);
  206.     XtFree(menu);
  207.  
  208.     if (Header->VMList == 0)
  209.       {
  210.         XtSetSensitive(Header->CustomVMAddMenuButton,0);
  211.         XtSetSensitive(Header->CustomVMAddVerbButton,0);
  212.         XtSetSensitive(Header->CustomVMSeparatorButton,0);
  213.         XtSetSensitive(Header->CustomVMRemoveButton,0);
  214.         XtSetSensitive(Header->CustomVMUpButton,0);
  215.         XtSetSensitive(Header->CustomVMDownButton,0);
  216.       }
  217.     else                
  218.       {
  219.         ListItem *item = Header->VMList->Selected;
  220.         XtSetSensitive(Header->CustomVMSeparatorButton,1);
  221.         XtSetSensitive(Header->CustomVMRemoveButton,(item!=0));
  222.         XtSetSensitive(Header->CustomVMUpButton,
  223.                        (item!=0 && item!=Header->VMList->First));
  224.         XtSetSensitive(Header->CustomVMDownButton,
  225.                        (item!=0 && item!=Header->VMList->Last));
  226.         sensitive = (Header->TempVerbList.Selected!=0);
  227.         if (sensitive)
  228.           sensitive=(MidasFindItemInList(Header->VMList,
  229.                      Header->TempVerbList.Selected->Entry)==0);
  230.         XtSetSensitive(Header->CustomVMAddVerbButton,sensitive);
  231.         sensitive = (Header->TempMenuList.Selected!=0);
  232.         if (sensitive)
  233.           {
  234.             char *entry = CustomAppendArrow(Header->TempMenuList.Selected->Entry);
  235.             sensitive=(MidasFindItemInList(Header->VMList,entry)==0);
  236.             XtFree(entry);
  237.           }
  238.         if (sensitive)
  239.           {
  240.             List *parent = ((List *) Header->TempMenuList.Selected->Pointer);
  241.             if (parent==0 || parent == Header->VMList) sensitive = 0;
  242.             else sensitive = (CustomIsChild(Header,parent,Header->VMList)==0);
  243.           }
  244.         XtSetSensitive(Header->CustomVMAddMenuButton,sensitive);
  245.       }
  246. }
  247. static CustomHeader *CustomFindHeader(w)
  248.       Widget w;
  249. {
  250.       Widget main;
  251.       CustomHeader *header;
  252.       int n = 0;
  253.       Arg args[10];
  254.       XtSetArg(args[n],XmNuserData , &header); n++;
  255.  
  256.       for (main=w;; main=XtParent(main)) 
  257.         {
  258.           XtGetValues(main,args,n);
  259.           if (header!=0 && header != (CustomHeader *) -1) return header;
  260.         }
  261. }
  262. static void CustomUpdateSensitivityCallback(w,closure,cbDataP)
  263.       Widget w; 
  264.       Opaque closure; 
  265.       XmAnyCallbackStruct *cbDataP;
  266. {
  267.     CustomHeader *Header = CustomFindHeader(w);
  268.     CustomUpdateSensitivity(Header);
  269. }
  270. static void CustomAddVerb(w,closure,cbDataP)
  271.       Widget w; 
  272.       Opaque closure; 
  273.       XmAnyCallbackStruct *cbDataP;
  274. {
  275.     int pos;
  276.     char *verb;
  277.     char *command;
  278.     ListItem *item;
  279.     CustomHeader *Header = CustomFindHeader(w);
  280.     Boolean istoggle;
  281.     VerbStruct *Verb;  
  282.  
  283.  
  284.     verb = XmTextGetString(Header->CustomVerbText);
  285.     command = XmTextGetString(Header->CustomCommandText);
  286.     istoggle = XmToggleButtonGetState(Header->CustomVerbIsToggle); 
  287.  
  288.     if (item = MidasFindItemInList(&Header->TempVerbList,verb)) 
  289.       {
  290.         Verb = (VerbStruct *) item->Pointer;  
  291.         XtFree(Verb->Command);
  292.         XtFree((char *) Verb); 
  293.       }
  294.     else
  295.       {
  296.         item = MidasAddItemToList(&Header->TempVerbList,verb);
  297.         pos = MidasFindItemPosInList(&Header->TempVerbList,item);
  298.         MidasSelectItemPosInList(&Header->TempVerbList,pos,FALSE);
  299.         CustomUpdatePositionsAdd(&Header->TempMenuList,pos,1);
  300.       }
  301.     XtFree(verb);
  302.  
  303.     Verb = XtNew(VerbStruct);
  304.     Verb->Command = command;
  305.     Verb->IsToggle = istoggle;
  306.  
  307.     Header->TempVerbList.Selected = item;
  308.     item->Pointer = Verb;
  309.     Header->Changed++;
  310.     CustomUpdateSensitivity(Header);
  311. }
  312. static void CustomSelVerb(w,closure,cbDataP)
  313.       Widget w; 
  314.       Opaque closure; 
  315.       XmListCallbackStruct *cbDataP;
  316. {
  317.     ListItem *item;
  318.     CustomHeader *Header = CustomFindHeader(w);
  319.     VerbStruct *Verb;
  320.     
  321.     item = MidasFindItemInListPos(&Header->TempVerbList,cbDataP->item_position); 
  322.     Header->TempVerbList.Selected = item;
  323.     XmTextSetString(Header->CustomVerbText,item->Entry);
  324.  
  325.     Verb = (VerbStruct *) item->Pointer;
  326.  
  327.     XmToggleButtonSetState(Header->CustomVerbIsToggle,Verb->IsToggle,FALSE);
  328.     XmTextSetString(Header->CustomCommandText,Verb->Command);
  329.  
  330.     CustomUpdateSensitivity(Header);
  331. }
  332. static void CustomDelVerb(w,closure,cbDataP)
  333.       Widget w; 
  334.       Opaque closure; 
  335.       XmAnyCallbackStruct *cbDataP;
  336. {
  337.     char *verb;
  338.     CustomHeader *Header = CustomFindHeader(w);
  339.     ListItem  *item = Header->TempVerbList.Selected; 
  340.     VerbStruct *Verb = (VerbStruct *) item->Pointer;
  341.  
  342.     int pos = MidasFindItemPosInList(&Header->TempVerbList,item);
  343.                            
  344.     XtFree(Verb->Command);
  345.   
  346.     CustomUpdatePositionsRemove(&Header->TempMenuList,pos,1);
  347.     MidasRemoveItemFromList(&Header->TempVerbList,item);
  348.                             
  349.     XmTextSetString(Header->CustomVerbText,"");
  350.     XmTextSetString(Header->CustomCommandText,"");
  351.     XmToggleButtonSetState(Header->CustomVerbIsToggle,FALSE,FALSE);
  352.     Header->TempVerbList.Selected = 0;
  353.     Header->Changed++;
  354.     CustomUpdateSensitivity(Header);
  355. }
  356. static void CustomAddMenu(w,closure,cbDataP)
  357.       Widget w; 
  358.       Opaque closure; 
  359.       XmAnyCallbackStruct *cbDataP;
  360. {
  361.     int pos;
  362.     char *menu;
  363.     ListItem *item;
  364.     CustomHeader *Header = CustomFindHeader(w);
  365.  
  366.     menu = XmTextGetString(Header->CustomMenuText);
  367.     XmTextSetString(Header->CustomMenuText,"");
  368.  
  369.     item = MidasAddItemToList(&Header->TempMenuList,menu);
  370.     pos = MidasFindItemPosInList(&Header->TempMenuList,item);
  371.     MidasSelectItemPosInList(&Header->TempMenuList,pos,FALSE);
  372.     CustomUpdatePositionsAdd(&Header->TempMenuList,pos,0);
  373.  
  374.     item->Pointer = MidasCreateEmptyList(menu);
  375.     Header->TempMenuList.Selected = item;
  376.     Header->Changed++;
  377.     CustomUpdateSensitivity(Header);
  378.     XtFree(menu);
  379. }
  380. static void CustomSelConfMenu(w,closure,cbDataP)
  381.       Widget w; 
  382.       Opaque closure; 
  383.       XmAnyCallbackStruct *cbDataP;
  384. {
  385.     char     label[100];
  386.     XmString string;
  387.     CustomHeader *Header = CustomFindHeader(w);
  388.  
  389.     strcpy(label,"Menu: "); 
  390.     if (Header->VMList!=0) MidasUnrealizeList(Header->VMList);  
  391.     Header->VMList = ((List *) Header->TempMenuList.Selected->Pointer);
  392.     MidasRealizeList(Header->VMList,Header->CustomVMList);
  393.     string = MidasCharToString(strcat(label,Header->TempMenuList.Selected->Entry));
  394.     CustomSetActiveMenu(Header,string);
  395.     XmStringFree(string);
  396.     CustomUpdateSensitivity(Header);
  397. }
  398. static void CustomSelMenu(w,closure,cbDataP)
  399.       Widget w; 
  400.       Opaque closure; 
  401.       XmListCallbackStruct *cbDataP;
  402. {
  403.     ListItem *item;
  404.     CustomHeader *Header = CustomFindHeader(w);
  405.     item = MidasFindItemInListPos(&Header->TempMenuList,cbDataP->item_position); 
  406.     Header->TempMenuList.Selected = item;
  407.     CustomUpdateSensitivity(Header);
  408. }
  409. static void CustomDelMenu(w,closure,cbDataP)
  410.       Widget w; 
  411.       Opaque closure; 
  412.       XmAnyCallbackStruct *cbDataP;
  413. {
  414.     char *menu;
  415.     CustomHeader *Header = CustomFindHeader(w);
  416.     int pos = MidasFindItemPosInList(&Header->TempMenuList,
  417.                                       Header->TempMenuList.Selected); 
  418.                             
  419.     CustomUpdatePositionsRemove(&Header->TempMenuList,pos,0);
  420.  
  421.     if (((List *) Header->TempMenuList.Selected->Pointer) == Header->VMList) 
  422.       {
  423.         XmString string;
  424.         MidasUnrealizeList(Header->VMList);  
  425.         Header->VMList=0;
  426.         string = MidasCharToString("No Menu Selected");
  427.         CustomSetActiveMenu(Header,string);
  428.         XmStringFree(string);
  429.       }
  430.     MidasDestroyList(Header->TempMenuList.Selected->Pointer);
  431.     Header->TempMenuList.Selected->Pointer = 0;
  432.     MidasRemoveItemFromList(&Header->TempMenuList,Header->TempMenuList.Selected); 
  433.     Header->TempMenuList.Selected = 0;
  434.     Header->Changed++;
  435.     CustomUpdateSensitivity(Header);
  436. }
  437. static void CustomVMAddSeparator(w,closure,cbDataP)
  438.       Widget w; 
  439.       Opaque closure; 
  440.       XmAnyCallbackStruct *cbDataP;
  441. {
  442.     ListItem *item; 
  443.     VerbInMenu *vm; 
  444.     CustomHeader *Header = CustomFindHeader(w);
  445.  
  446.     item = MidasAddItemToListPos(Header->VMList,"......",0);
  447.     MidasSelectItemPosInList(Header->VMList,0,FALSE);
  448.  
  449.     vm = XtNew(VerbInMenu);
  450.     vm->Menu = 0;
  451.     vm->Verb = 0;
  452.  
  453.     item->Pointer = vm;
  454.     Header->VMList->Selected = item;
  455.     Header->Changed++;
  456.     CustomUpdateSensitivity(Header);
  457. }
  458. static void CustomVMAddVerb(w,closure,cbDataP)
  459.       Widget w; 
  460.       Opaque closure; 
  461.       XmAnyCallbackStruct *cbDataP;
  462. {
  463.     char *verb; 
  464.     VerbInMenu *vm; 
  465.     ListItem *item; 
  466.     CustomHeader *Header = CustomFindHeader(w);
  467.  
  468.     verb = Header->TempVerbList.Selected->Entry;
  469.     item = MidasAddItemToListPos(Header->VMList,verb,0);
  470.     MidasSelectItemPosInList(Header->VMList,0,FALSE);
  471.  
  472.     vm = XtNew(VerbInMenu);
  473.     vm->Menu = 0;
  474.     vm->Verb = MidasFindItemPosInList(&Header->TempVerbList,
  475.                                        Header->TempVerbList.Selected);
  476.     item->Pointer = vm;
  477.  
  478.     Header->VMList->Selected = item;
  479.     Header->Changed++;
  480.     CustomUpdateSensitivity(Header);
  481. }
  482. static void CustomSelConfVerb(w,closure,cbDataP)
  483.       Widget w; 
  484.       Opaque closure; 
  485.       XmAnyCallbackStruct *cbDataP;
  486. {
  487.     CustomHeader *Header = CustomFindHeader(w);
  488.     if (XtIsSensitive(Header->CustomVMAddVerbButton)) 
  489.       CustomVMAddVerb(w,closure,(XmAnyCallbackStruct *) cbDataP);
  490. }
  491. static void CustomVMAddMenu(w,closure,cbDataP)
  492.       Widget w; 
  493.       Opaque closure; 
  494.       XmAnyCallbackStruct *cbDataP;
  495. {
  496.     char *menu, *arrow; 
  497.     VerbInMenu *vm; 
  498.     ListItem *item; 
  499.     CustomHeader *Header = CustomFindHeader(w);
  500.  
  501.     menu = Header->TempMenuList.Selected->Entry;
  502.     arrow = CustomAppendArrow(menu);
  503.     item = MidasAddItemToListPos(Header->VMList,arrow,0);
  504.     MidasSelectItemPosInList(Header->VMList,0,FALSE);
  505.     XtFree(arrow);
  506.    
  507.     vm = XtNew(VerbInMenu);
  508.     vm->Menu = MidasFindItemPosInList(&Header->TempMenuList,
  509.                                        Header->TempMenuList.Selected);
  510.     vm->Verb = 0;
  511.    
  512.     item->Pointer = vm;
  513.  
  514.     Header->VMList->Selected = item;
  515.     Header->Changed++;
  516.     CustomUpdateSensitivity(Header);
  517. }
  518. static void CustomVMSel(w,closure,cbDataP)
  519.       Widget w; 
  520.       Opaque closure; 
  521.       XmListCallbackStruct *cbDataP;
  522. {
  523.     ListItem *item;
  524.     CustomHeader *Header = CustomFindHeader(w);
  525.  
  526.     item = MidasFindItemInListPos(Header->VMList,cbDataP->item_position);
  527.     Header->VMList->Selected = item;
  528.     CustomUpdateSensitivity(Header);
  529. }
  530. static void CustomVMSelConf(w,closure,cbDataP)
  531.       Widget w; 
  532.       Opaque closure; 
  533.       XmListCallbackStruct *cbDataP;
  534. {
  535.     VerbInMenu *vm;
  536.     ListItem *item;
  537.     CustomHeader *Header = CustomFindHeader(w);
  538.  
  539.     item = MidasFindItemInListPos(Header->VMList,cbDataP->item_position);
  540.     vm = ((VerbInMenu *) item->Pointer);
  541.     if      (vm->Verb != 0) 
  542.       { 
  543.         ListItem *verb = MidasFindItemInListPos(&Header->TempVerbList,vm->Verb);
  544.         XmString string = MidasCharToString(verb->Entry);
  545.         XmListSelectItem(Header->CustomVerbList,string,1);
  546.         XmStringFree(string);
  547.       }
  548.     else if (vm->Menu != 0) 
  549.       {
  550.         ListItem *menu = MidasFindItemInListPos(&Header->TempMenuList,vm->Menu);
  551.         XmString string = MidasCharToString(menu->Entry);
  552.         XmListSelectItem(Header->CustomMenuList,string,1);
  553.         XmStringFree(string);
  554.       }
  555. }
  556. static void CustomVMDel(w,closure,cbDataP)
  557.       Widget w; 
  558.       Opaque closure; 
  559.       XmAnyCallbackStruct *cbDataP;
  560. {
  561.     char *menu;
  562.     ListItem *item;
  563.     CustomHeader *Header = CustomFindHeader(w);
  564.  
  565.     MidasRemoveItemFromList(Header->VMList,Header->VMList->Selected); 
  566.     Header->VMList->Selected = 0;
  567.     Header->Changed++;
  568.     CustomUpdateSensitivity(Header);
  569. }
  570. static void CustomMoveUp(Header,item,dir)
  571.       CustomHeader *Header;
  572.       ListItem     *item;
  573.       int           dir;
  574. {
  575.     XmString NewItems[2];
  576.  
  577.     ListItem *i;
  578.     ListItem *swap = item->Prev;
  579.     int position=0;
  580.  
  581.     for (i = Header->VMList->First; i != 0; i = i->Next) 
  582.       {
  583.         position++;
  584.         if (i == item) break;
  585.       }
  586.  
  587.     NewItems[0] = MidasCharToString(item->Entry); 
  588.     NewItems[1] = MidasCharToString(swap->Entry); 
  589.     
  590.     XmListReplaceItemsPos(Header->VMList->W,NewItems,2,--position);
  591.  
  592.     XmStringFree(NewItems[0]);
  593.     XmStringFree(NewItems[1]);
  594.  
  595.     if (dir) 
  596.       {
  597.         XmListDeselectPos(Header->VMList->W,position);
  598.         XmListSelectPos(Header->VMList->W,position+1,0);
  599.       }
  600.     else 
  601.       {
  602.         XmListSelectPos(Header->VMList->W,position,0);
  603.         XmListDeselectPos(Header->VMList->W,position+1);
  604.       }
  605.  
  606.     if (Header->VMList->First == swap) Header->VMList->First = item; 
  607.     else                               swap->Prev->Next = item;
  608.     if (Header->VMList->Last  == item) Header->VMList->Last  = swap; 
  609.     else                               item->Next->Prev = swap;
  610.     item->Prev = swap->Prev;
  611.     swap->Next = item->Next;
  612.     item->Next = swap;
  613.     swap->Prev = item;
  614.     Header->Changed++;
  615.     CustomUpdateSensitivity(Header);
  616. }
  617. static void CustomVMUp(w,closure,cbDataP)
  618.       Widget w; 
  619.       Opaque closure; 
  620.       XmAnyCallbackStruct *cbDataP;
  621. {
  622.     CustomHeader *Header = CustomFindHeader(w);
  623.     CustomMoveUp(Header,Header->VMList->Selected,0);
  624. }
  625. static void CustomVMDown(w,closure,cbDataP)
  626.       Widget w; 
  627.       Opaque closure; 
  628.       XmAnyCallbackStruct *cbDataP;
  629. {
  630.     CustomHeader *Header = CustomFindHeader(w);
  631.     CustomMoveUp(Header,Header->VMList->Selected->Next,1);
  632. }
  633. static void CustomDispatchCommand(w,tag,cbDataP)
  634.       Widget w; 
  635.       Opaque tag; 
  636.       XmAnyCallbackStruct *cbDataP;
  637. {
  638.    MidasDispatchCommandCallback(w,tag,cbDataP);
  639. }
  640. static void CustomCreateCallback(w,tag,cbDataP)
  641.       Widget w; 
  642.       int *tag; 
  643.       XmAnyCallbackStruct *cbDataP;
  644. {
  645.     ListItem *item = CustomHeaders.Selected;
  646.     CustomHeader *Header = item->Pointer;
  647.  
  648.     if      (*tag ==  1) Header->CustomCommandText       = w; 
  649.     else if (*tag ==  2) Header->CustomVMUpButton        = w;
  650.     else if (*tag ==  3) Header->CustomVMDownButton      = w;
  651.     else if (*tag ==  4) Header->CustomVMAddVerbButton   = w;
  652.     else if (*tag ==  5) Header->CustomVMAddMenuButton   = w;
  653.     else if (*tag ==  6) Header->CustomVMSeparatorButton = w;
  654.     else if (*tag ==  7) Header->CustomVMRemoveButton    = w;
  655.     else if (*tag ==  8) Header->CustomVMList            = w;
  656.     else if (*tag ==  9) Header->CustomOKButton          = w;
  657.     else if (*tag == 10) Header->CustomApplyButton       = w;
  658.     else if (*tag == 11) Header->CustomCancelButton      = w;
  659.     else if (*tag == 12) Header->CustomResetButton       = w;
  660.     else if (*tag == 13) Header->CustomVerbList          = w;
  661.     else if (*tag == 14) Header->CustomVerbText          = w;
  662.     else if (*tag == 15) Header->CustomVerbAddButton     = w;
  663.     else if (*tag == 16) Header->CustomVerbDeleteButton  = w;
  664.     else if (*tag == 17) Header->CustomMenuList          = w;
  665.     else if (*tag == 18) Header->CustomMenuText          = w;
  666.     else if (*tag == 19) Header->CustomMenuAddButton     = w;
  667.     else if (*tag == 20) Header->CustomMenuDeleteButton  = w;
  668.     else if (*tag == 21) Header->CustomVMActiveLabel     = w;
  669.     else if (*tag == 22) Header->CustomVerbIsToggle      = w;
  670. }                      
  671. static void CustomDestroyMenu(w)
  672.       Widget w;
  673. {
  674.       Widget *list = DXmChildren(w);
  675.       int n = DXmNumChildren(w);
  676.  
  677.       for (; n > 0; n--) 
  678.         { 
  679.           XtUnmanageChild(*list);
  680.           XtDestroyWidget(*list);
  681.           list++;
  682.         }
  683. }
  684. static char *strtrn(in,from,to)
  685. char *in; 
  686. char from; 
  687. char to;
  688. {
  689.       char *p = in;
  690.       for (; *p != 0; p++) if (*p == from) *p = to;
  691.       return in;
  692. }
  693. static void CustomBuildMenu(Header,w,menu)
  694.       CustomHeader *Header;
  695.       Widget w; 
  696.       List   *menu;
  697. {
  698.       Widget child[4000];
  699.       ListItem *j;
  700.       int m=0;
  701.  
  702.       for (j = menu->First; j != 0; j = j->Next)
  703.         {
  704.           VerbInMenu *vm = ((VerbInMenu *) j->Pointer);
  705.           if (vm->Verb != 0) 
  706.             {
  707.               ListItem *verb = MidasFindItemInListPos(&Header->VerbList,vm->Verb);
  708.               XmString verbname = MidasCharToString(verb->Entry);
  709.               VerbStruct *Verb = (VerbStruct *) verb->Pointer;
  710.  
  711.               Arg args[10];
  712.               int n = 0;          
  713.               char *name = strtrn(XtNewString(verb->Entry),' ','_');              
  714.  
  715.               strtrn(name,'.','_');          
  716.  
  717.               if (Verb->IsToggle)
  718.                 {
  719.                   XtSetArg(args[n],XmNlabelString, verbname); n++;
  720.                   child[m] = XmCreateToggleButtonGadget(w,name,args,n);
  721.                   MidasSetupWidget(child[m]);
  722.                   XtAddCallback(child[m++],XmNvalueChangedCallback,
  723.                                 CustomDispatchCommand,Verb->Command);
  724.                  }
  725.               else
  726.                 {
  727.                   XtSetArg(args[n],XmNlabelString, verbname); n++;
  728.                   child[m] = XmCreatePushButtonGadget(w,name,args,n);
  729.                   MidasSetupWidget(child[m]);
  730.                   XtAddCallback(child[m++],XmNactivateCallback,
  731.                                 CustomDispatchCommand,Verb->Command);
  732.                 } 
  733.               XtFree(name);
  734.               XmStringFree(verbname);
  735.             }
  736.           else if (vm->Menu != 0) 
  737.             {
  738.               ListItem *menu = MidasFindItemInListPos(&Header->MenuList,vm->Menu);
  739.               XmString menuname = MidasCharToString(menu->Entry);
  740.               char *name = strtrn(XtNewString(menu->Entry),' ','_');
  741.               Widget submenu = XmCreatePulldownMenu(w,name,NULL,0);
  742.               int n = 0;
  743.               Arg args[10];
  744.               XtSetArg(args[n],XmNlabelString , menuname ); n++;
  745.               XtSetArg(args[n],XmNsubMenuId   , submenu  ); n++;
  746.               child[m] = XmCreateCascadeButtonGadget(w,name,args,n);
  747. /*
  748.  *  If the last item in a menu is a HELP menu, force it to be right aligned
  749.  */
  750.  
  751.               if (j->Next == NULL && strcmp(name,"Help")==0)
  752.                 {
  753.                   n = 0;
  754.                   XtSetArg(args[n],XmNmenuHelpWidget,child[m]); n++;
  755.                   XtSetValues(w,args,n);
  756.                 }
  757.  
  758.               MidasSetupWidget(submenu);
  759.               MidasSetupWidget(child[m++]);
  760.               XtFree(name);
  761.               XmStringFree(menuname);
  762.  
  763.               CustomBuildMenu(Header,submenu,menu->Pointer); 
  764.             }
  765.           else 
  766.             {
  767.               child[m++] = XmCreateSeparatorGadget(w," ",NULL,0);
  768.             }
  769.         }
  770.       XtManageChildren(child,m);
  771. }
  772. static void CustomUpdateMenus(Header)
  773.     CustomHeader *Header;
  774. {
  775.     ListItem *connect = Header->ConnectList.First;
  776.     for (; connect != 0 ; connect = connect->Next )
  777.       {
  778.         Link *link = connect->Pointer;
  779.         ListItem *menu = MidasFindItemInList(&Header->MenuList,connect->Entry);
  780.         CustomDestroyMenu(link->Widget);
  781.         CustomBuildMenu(Header,link->Widget,menu->Pointer);
  782.       }
  783. }
  784. static VerbStruct *CustomCopyVerbListElement(Old)
  785.     VerbStruct *Old;
  786.     VerbStruct *New = XtNew(VerbStruct);
  787.  
  788.     New->IsToggle = Old->IsToggle;
  789.     New->Command = XtNewString(Old->Command);  
  790.  
  791.     return New;
  792. }
  793. static VerbInMenu *CustomCopyVMListElement(vm)
  794.     VerbInMenu *vm;
  795. {
  796.     return (VerbInMenu *) memcpy(XtMalloc(sizeof(VerbInMenu)),vm,sizeof(VerbInMenu));
  797. }
  798. static List *CustomCopyMenuListElement(L)
  799.     List *L;
  800. {
  801.     List *New = MidasCreateEmptyList("");
  802.     MidasCopyList(L,New,(MidasCopyListRtn)CustomCopyVMListElement);
  803.     return New;
  804. }
  805. static void CustomCopyVerbList(Old,New)
  806.     List *Old;
  807.     List *New;
  808. {
  809.     MidasCopyList(Old,New,(MidasCopyListRtn)CustomCopyVerbListElement);
  810. }
  811. static void CustomCopyMenuList(Old,New)
  812.     List *Old;
  813.     List *New;
  814. {
  815.     MidasCopyList(Old,New,(MidasCopyListRtn)CustomCopyMenuListElement);
  816. }
  817. static void CustomCleanup(Header)
  818.    CustomHeader *Header;
  819. {
  820.     XmString string;
  821.     if (Header->VMList != 0) MidasUnrealizeList(Header->VMList);  
  822.     MidasUnrealizeList(&Header->TempVerbList);
  823.     MidasUnrealizeList(&Header->TempMenuList);
  824.     Header->VMList=0;
  825.     string = MidasCharToString("No Menu Selected");
  826.     CustomSetActiveMenu(Header,string);
  827.     XmStringFree(string);
  828.     XmTextSetString(Header->CustomVerbText,"");
  829.     XmTextSetString(Header->CustomMenuText,"");
  830.     XmTextSetString(Header->CustomCommandText,"");
  831. }
  832. static void CustomApply(w,tag,cbDataP)
  833.       Widget w; 
  834.       int    *tag; 
  835.       XmSelectionBoxCallbackStruct *cbDataP;
  836. {
  837.     ListItem *i;
  838.     CustomHeader *Header = CustomFindHeader(w);
  839.     Header->Changed = 0;
  840.     Header->Modified++;
  841.  
  842.     for (i = Header->MenuList.First ; i != 0 ; i = i->Next )
  843.       {
  844.         MidasDestroyList(i->Pointer);
  845.         i->Pointer = 0;
  846.       }
  847.     for (i = Header->VerbList.First ; i != 0 ; i = i->Next )
  848.       {
  849.         VerbStruct *Verb = (VerbStruct *) i->Pointer;
  850.         XtFree(Verb->Command);
  851.         XtFree((char *) Verb);
  852.         i->Pointer = 0;
  853.       }
  854.     MidasEmptyList(&Header->VerbList);
  855.     MidasEmptyList(&Header->MenuList);
  856.  
  857.     Header->VerbList = NullList;
  858.     Header->MenuList = NullList;
  859.  
  860.     CustomCopyVerbList(&Header->TempVerbList,&Header->VerbList);
  861.     CustomCopyMenuList(&Header->TempMenuList,&Header->MenuList);
  862.  
  863.     CustomUpdateMenus(Header);
  864.  
  865.     CustomUpdateSensitivity(Header);
  866. }
  867. static void CustomReset(w,tag,cbDataP)
  868.       Widget w; 
  869.       int    *tag; 
  870.       XmSelectionBoxCallbackStruct *cbDataP;
  871. {
  872.     CustomHeader *Header = CustomFindHeader(w);
  873.     ListItem *i;
  874.  
  875.     CustomCleanup(Header);
  876.  
  877.     for (i = Header->TempMenuList.First ; i != 0 ; i = i->Next )
  878.       {
  879.         MidasDestroyList(i->Pointer);
  880.         i->Pointer = 0;
  881.       }
  882.     for (i = Header->TempVerbList.First ; i != 0 ; i = i->Next )
  883.       {
  884.         VerbStruct *Verb = (VerbStruct *) i->Pointer;
  885.         XtFree(Verb->Command);
  886.         XtFree((char *) Verb);
  887.         i->Pointer = 0;
  888.       }
  889.  
  890.     MidasEmptyList(&Header->TempVerbList);
  891.     MidasEmptyList(&Header->TempMenuList);
  892.  
  893.     Header->TempVerbList = NullList;
  894.     Header->TempMenuList = NullList;
  895.  
  896.     CustomCopyVerbList(&Header->VerbList,&Header->TempVerbList);
  897.     CustomCopyMenuList(&Header->MenuList,&Header->TempMenuList);
  898.  
  899.     MidasRealizeList(&Header->TempVerbList,Header->CustomVerbList);
  900.     MidasRealizeList(&Header->TempMenuList,Header->CustomMenuList);
  901.     Header->Changed = 0;
  902.     CustomUpdateSensitivity(Header);
  903. }
  904. static void CustomCancel(w,tag,cbDataP)
  905.       Widget w; 
  906.       int    *tag; 
  907.       XmSelectionBoxCallbackStruct *cbDataP;
  908. {
  909.     ListItem *i;
  910.     CustomHeader *Header = CustomFindHeader(w);
  911.  
  912.     XtUnmanageChild(Header->Fetched);
  913.     CustomCleanup(Header);
  914.  
  915.     for (i = Header->TempMenuList.First ; i != 0 ; i = i->Next )
  916.       {
  917.         MidasDestroyList(i->Pointer);
  918.         i->Pointer = 0;
  919.       }
  920.     for (i = Header->TempVerbList.First ; i != 0 ; i = i->Next )
  921.       {
  922.         VerbStruct *Verb = (VerbStruct *) i->Pointer;
  923.         XtFree(Verb->Command);
  924.         XtFree((char *) Verb);
  925.         i->Pointer = 0;
  926.       }
  927.     MidasEmptyList(&Header->TempVerbList);
  928.     MidasEmptyList(&Header->TempMenuList);
  929.  
  930.     Header->TempVerbList = NullList;
  931.     Header->TempMenuList = NullList;
  932.  
  933. }
  934. static void CustomOk(w,tag,cbDataP)
  935.       Widget w; 
  936.       int    *tag; 
  937.       XmSelectionBoxCallbackStruct *cbDataP;
  938. {
  939.     CustomHeader *Header = CustomFindHeader(w);
  940.     ListItem *i;
  941.  
  942.     CustomCleanup(Header);
  943.  
  944.     if (Header->Changed != 0)
  945.       {  
  946.         for (i = Header->MenuList.First ; i != 0 ; i = i->Next )
  947.           {
  948.             MidasDestroyList(i->Pointer);
  949.             i->Pointer = 0;
  950.           }
  951.         for (i = Header->VerbList.First ; i != 0 ; i = i->Next )
  952.           {
  953.             VerbStruct *Verb = (VerbStruct *) i->Pointer;
  954.             XtFree(Verb->Command);
  955.             XtFree((char *) Verb);
  956.             i->Pointer = 0;
  957.           }
  958.         MidasEmptyList(&Header->VerbList);
  959.         MidasEmptyList(&Header->MenuList);
  960.  
  961.         Header->VerbList = Header->TempVerbList;
  962.         Header->MenuList = Header->TempMenuList;
  963.  
  964.         CustomUpdateMenus(Header);
  965.         Header->Modified++;
  966.       }
  967.     else 
  968.       {
  969.         for (i = Header->TempMenuList.First ; i != 0 ; i = i->Next )
  970.           {
  971.             MidasDestroyList(i->Pointer);
  972.             i->Pointer = 0;
  973.           }
  974.         for (i = Header->TempVerbList.First ; i != 0 ; i = i->Next )
  975.           {
  976.             VerbStruct *Verb = (VerbStruct *) i->Pointer;
  977.             XtFree(Verb->Command);
  978.             XtFree((char *) Verb);
  979.             i->Pointer = 0;
  980.           }
  981.         MidasEmptyList(&Header->TempVerbList);
  982.         MidasEmptyList(&Header->TempMenuList);
  983.       }
  984.     Header->TempVerbList = NullList;
  985.     Header->TempVerbList = NullList;
  986.  
  987.     XtUnmanageChild(Header->Fetched);
  988. }
  989. static void CustomWrite(Header,Name)
  990.     CustomHeader *Header;
  991.     char *Name;
  992. {
  993.     ListItem *i,*j;
  994.     List *menu;
  995.     char list[4096];
  996.     char value[4096];
  997.     char specifier[80];
  998.     char *l = list;
  999.     MidasShell *ms = MidasGetShell(Header->Parent);
  1000.     XrmDatabase *database = &ms->Database;
  1001.     int n= 0 ;
  1002.  
  1003.     for (i = Header->VerbList.First; i != 0; i = i->Next)
  1004.       {
  1005.         VerbStruct *Verb = (VerbStruct *) i->Pointer; 
  1006.         strcpy(l,i->Entry);
  1007.  
  1008.         l += strlen(i->Entry);
  1009.         *l++ = '#';
  1010.  
  1011.         sprintf(specifier,"CUSTOM.%s.Verb.%d",Name,++n);
  1012.  
  1013.         if (Verb->IsToggle) sprintf(value,"#%s",Verb->Command);
  1014.         else                sprintf(value,"%s" ,Verb->Command);
  1015.  
  1016.         XrmPutStringResource(database,specifier,value);
  1017.       }
  1018.  
  1019.     *(--l) = '\0';
  1020.     sprintf(specifier,"CUSTOM.%s.Verbs",Name);
  1021.     XrmPutStringResource(database,specifier,list);
  1022.  
  1023.     l = list;
  1024.     n = 0; 
  1025.     
  1026.     for (i = Header->MenuList.First; i != 0; i = i->Next)
  1027.       {
  1028.         char *v = value;
  1029.  
  1030.         menu = i->Pointer;
  1031.  
  1032.         strcpy(l,i->Entry);
  1033.         l += strlen(i->Entry);
  1034.         *l++ = '#';
  1035.  
  1036.         for (j = menu->First; j != 0; j = j->Next)
  1037.           {
  1038.             VerbInMenu *vm = ((VerbInMenu *) j->Pointer);
  1039.             int pos = 0;
  1040.  
  1041.             if      (vm->Verb != 0) pos = vm->Verb;
  1042.             else if (vm->Menu != 0) pos = -vm->Menu;
  1043.  
  1044.             sprintf(v,"%s\\%d#",j->Entry,pos);
  1045.             v += strlen(v);
  1046.           }
  1047.         *(--v) = '\0';
  1048.         sprintf(specifier,"CUSTOM.%s.Menu.%d",Name,++n);
  1049.         XrmPutStringResource(database,specifier,value);
  1050.       }
  1051.  
  1052.     *(--l) = '\0';
  1053.     sprintf(specifier,"CUSTOM.%s.Menus",Name);
  1054.     XrmPutStringResource(database,specifier,list);
  1055.  
  1056.     ms->Changes++;
  1057.     Header->Modified = 0;
  1058. }
  1059. static void CustomReadOld(Header,Name,UserDefaults)
  1060.     CustomHeader *Header;
  1061.     char         *Name;
  1062.     int          UserDefaults;
  1063. {
  1064.     char buffer[4000] , name[80];
  1065.     FILE *file;
  1066.  
  1067.     if (UserDefaults)
  1068.       {
  1069. #ifdef VAX
  1070.         sprintf(name,"DECW$USER_DEFAULTS:MIDAS_%s.DAT",Name);
  1071. #else
  1072.         sprintf(name,".Midas_%src",Name);
  1073. #endif
  1074.         file = fopen(name,"r");
  1075.       }
  1076.     if (file == 0)
  1077.       {
  1078.         sprintf(name,"DECW$SYSTEM_DEFAULTS:MIDAS_%s.DAT",Name);
  1079.         file = fopen(name,"r");
  1080.       }
  1081.     if (file == 0)
  1082.        file = fopen("DECW$SYSTEM_DEFAULTS:MIDAS_CUSTOM.DAT","r");
  1083.  
  1084.     if (file == 0) MidasError("Could not open customization file for %s",Name);
  1085.     
  1086.     for (;;) 
  1087.       {
  1088.         int c = fgetc(file);
  1089.         if (c == EOF) break;
  1090.         if (c == '$')
  1091.           {
  1092.             int i,j,l;
  1093.             char type[6],*p;
  1094.  
  1095.             p = type;
  1096.             *p++ = fgetc(file);
  1097.             *p++ = fgetc(file);
  1098.             *p++ = fgetc(file);
  1099.             *p++ = fgetc(file);
  1100.             *p++ = fgetc(file);
  1101.             *p = '\0';
  1102.  
  1103.             for (l=0;;l++)
  1104.               {
  1105.                  c = fgetc(file);
  1106.                  buffer[l] = c;
  1107.  
  1108.                  if (c == '{') j=l;
  1109.                  if (c == '}' | c == EOF) break;
  1110.               }
  1111.  
  1112.             i = 1;
  1113.             buffer[j-1] = '\0';
  1114.             j += 2;
  1115.  
  1116.             if (strcmp(type,"Verb:") == 0)
  1117.               {
  1118.                 VerbStruct *Verb = XtNew(VerbStruct); 
  1119.                 ListItem *item; 
  1120.                 if (buffer[i]=='#') 
  1121.                   {
  1122.                     i++;
  1123.                     Verb->IsToggle = TRUE;
  1124.                   }
  1125.                 else Verb->IsToggle = FALSE;       
  1126.                 item = MidasAddItemToList(&Header->VerbList,&buffer[i]);
  1127.                 buffer[l-1] = '\0';
  1128.                 item->Pointer = Verb;
  1129.                 Verb->Command = XtNewString(&buffer[j]);
  1130.               }         
  1131.             else if (strcmp(type,"Menu:") == 0)
  1132.               {
  1133.                 int k;
  1134.                 List *list;
  1135.  
  1136.                 ListItem *item = MidasAddItemToListPos(&Header->MenuList,&buffer[i],0);
  1137.  
  1138.                 list = XtNew(List);
  1139.                 list->First    = 0;
  1140.                 list->Last     = 0;
  1141.                 list->Selected = 0;
  1142.                 list->W        = 0;
  1143.                 item->Pointer = list;
  1144.                 for (;;)
  1145.                   {
  1146.                     VerbInMenu *vm;
  1147.                     int pos;
  1148.  
  1149.                     for (;buffer[j]==' ';j++);
  1150.                     for (k=j; buffer[k]!='\\' && buffer[k]!='}'; k++);
  1151.                     if (buffer[k]=='}') break;
  1152.                     buffer[k]='\0';
  1153.                     item = MidasAddItemToListPos(list,&buffer[j],0);
  1154.                     vm = XtNew(VerbInMenu);
  1155.                     item->Pointer = vm;
  1156.                     vm->Menu = 0; 
  1157.                     vm->Verb = 0; 
  1158.                     j = k+1;
  1159.                     for (k=j; buffer[k]!='\n'; k++);
  1160.                     buffer[k]='\0';
  1161.                     pos = atoi(&buffer[j]);
  1162.                     if      (pos > 0) vm->Verb = pos;
  1163.                     else if (pos < 0) vm->Menu = -pos;
  1164.                     j = k+1;
  1165.                   }
  1166.               }
  1167.           }
  1168.       }
  1169.     fclose(file);
  1170. }
  1171. static void CustomRead(Header,Name,UserDefaults) 
  1172.     CustomHeader *Header;
  1173.     char         *Name;
  1174.     int          UserDefaults;
  1175. {
  1176.     XrmDatabase database = XtDatabase(XtDisplay(Header->Parent));
  1177.     char specifier[80];
  1178.     char *type;
  1179.     XrmRepresentation rep;
  1180.     char *Verbs, *verb;
  1181.     char *Menus, *menu;
  1182.     XrmValue value;
  1183.     Boolean found;
  1184.     int n = 0;
  1185.     XrmHashTable root[10]; 
  1186.     XrmQuark     quarks[3]; 
  1187.  
  1188.  
  1189. /*
  1190.  * Start by reading the lists of verbs and menus
  1191.  */
  1192.     sprintf(specifier,"CUSTOM.%s.Verbs",Name);
  1193.  
  1194.     found = XrmGetResource(database,specifier,specifier,&type,&value);
  1195.     
  1196.     if (!found)
  1197.       {
  1198.         CustomReadOld(Header,Name,UserDefaults);
  1199.         return;
  1200.       }
  1201.     Verbs = XtNewString(value.addr);
  1202.  
  1203.     sprintf(specifier,"CUSTOM.%s.Menus",Name);
  1204.     found = XrmGetResource(database,specifier,specifier,&type,&value);
  1205.     Menus = XtNewString(value.addr);
  1206.     
  1207.     sprintf(specifier,"CUSTOM.%s.Verb",Name);
  1208.     XrmStringToNameList(specifier,quarks);
  1209.     
  1210.     XrmQGetSearchList(database,quarks,quarks,root,XtNumber(root)); 
  1211.  
  1212.     for (verb = strtok(Verbs,"#"); verb != NULL; verb = strtok(NULL,"#"))
  1213.       {
  1214.         VerbStruct *Verb = XtNew(VerbStruct); 
  1215.         ListItem *item = MidasAddItemToListPos(&Header->VerbList,verb,0); 
  1216.         char name[8];
  1217.         char *command;
  1218.         
  1219.         sprintf(name,"%d",++n);
  1220.         XrmQGetSearchResource(root,XrmStringToName(name),XrmStringToClass(name),&rep,&value);
  1221.         command = value.addr;
  1222.  
  1223.         if (Verb->IsToggle = (*command == '#')) command++; 
  1224.  
  1225.         item->Pointer = Verb;
  1226.         Verb->Command = XtNewString(command);
  1227.       } 
  1228.     
  1229.     n = 0;
  1230.     sprintf(specifier,"CUSTOM.%s.Menu",Name);
  1231.     XrmStringToNameList(specifier,quarks);
  1232.     
  1233.     XrmQGetSearchList(database,quarks,quarks,root,XtNumber(root)); 
  1234.  
  1235.     for (menu = strtok(Menus,"#"); menu != NULL; menu = strtok(NULL,"#"))
  1236.       {
  1237.         char *menuitems, *p;
  1238.         char name[8];
  1239.         List *list = MidasCreateEmptyList("");
  1240.         ListItem *item = MidasAddItemToListPos(&Header->MenuList,menu,0);
  1241.         item->Pointer = list;
  1242.  
  1243.         sprintf(name,"%d",++n);
  1244.         XrmQGetSearchResource(root,XrmStringToName(name),XrmStringToClass(name),&rep,&value);
  1245.         menuitems = XtNewString(value.addr);
  1246.  
  1247.         for (p = menuitems; *p != '\0'; p++)
  1248.           {
  1249.             VerbInMenu *vm = XtNew(VerbInMenu);
  1250.             int pos;
  1251.             ListItem *item;
  1252.  
  1253.             for (verb = p; *p != '\\'; p++);
  1254.             *p = '\0';
  1255.  
  1256.             item = MidasAddItemToListPos(list,verb,0);
  1257.             item->Pointer = vm;
  1258.  
  1259.             vm->Menu = 0; 
  1260.             vm->Verb = 0; 
  1261.  
  1262.             for (verb = ++p; *p != '#' && *p != '\0'; p++);
  1263.  
  1264.             pos = atoi(verb);
  1265.             if      (pos > 0) vm->Verb = pos;
  1266.             else if (pos < 0) vm->Menu = -pos;
  1267.  
  1268.             if (*p == '\0') break;
  1269.           }
  1270.         XtFree(menuitems);
  1271.       } 
  1272.  
  1273.     XtFree(Verbs);
  1274.     XtFree(Menus);
  1275. }
  1276. static void CustomDisconnect(w,connect,cbDataP)
  1277.       Widget w; 
  1278.       ListItem *connect; 
  1279.       XmSelectionBoxCallbackStruct *cbDataP;
  1280. {
  1281.   Link *link = connect->Pointer;
  1282.   CustomHeader *Header = link->Header;
  1283.   MidasRemoveItemFromList(&Header->ConnectList,connect);
  1284. }
  1285. void CustomWriteUser(name,entry)
  1286.       char   *name;
  1287.       char   *entry;
  1288. {
  1289.     CustomHeader *Header;
  1290.     ListItem *item = MidasFindItemInList(&CustomHeaders,name);
  1291.     char *fname;
  1292.  
  1293.     if (item == 0) return;
  1294.  
  1295.     Header = item->Pointer;
  1296.     if (entry==0) fname=name;
  1297.     else          fname=entry;
  1298.  
  1299.     CustomWrite(Header,fname);
  1300. }
  1301. void CustomReadUser(name,entry)
  1302.       char   *name;
  1303.       char   *entry;
  1304. {
  1305.     CustomHeader *Header;
  1306.     ListItem *item = MidasFindItemInList(&CustomHeaders,name);
  1307.     char *fname;
  1308.  
  1309.     if (item == 0) return;
  1310.  
  1311.     Header = item->Pointer;
  1312.     if (entry==0) fname=name;
  1313.     else          fname=entry;
  1314.  
  1315.     CustomRead(Header,fname,1);
  1316. }
  1317. void CustomReadSystem(name,entry)
  1318.       char   *name;
  1319.       char   *entry;
  1320. {
  1321.     CustomHeader *Header;
  1322.     ListItem *item = MidasFindItemInList(&CustomHeaders,name);
  1323.     char *fname;
  1324.  
  1325.     if (item == 0) return;
  1326.  
  1327.     Header = item->Pointer;
  1328.     if (entry==0) fname=name;
  1329.     else          fname=entry;
  1330.  
  1331.     CustomRead(Header,fname,0);
  1332. }
  1333. void CustomConnect(name,entry,w)
  1334.       char   *name;
  1335.       char   *entry;
  1336.       Widget w;
  1337. {
  1338.     CustomHeader *Header;
  1339.     ListItem *item = MidasFindItemInList(&CustomHeaders,name);
  1340.     ListItem *menu, *connect; 
  1341.     Link *link;
  1342.     int pos;
  1343.  
  1344.     if (item == 0) return;
  1345.  
  1346.     Header = item->Pointer;
  1347.     menu = MidasFindItemInList(&Header->MenuList,entry);
  1348.     if (menu==0)
  1349.       {
  1350.         menu = MidasAddItemToList(&Header->MenuList,entry);
  1351.         pos = MidasFindItemPosInList(&Header->MenuList,menu);
  1352.         CustomUpdatePositionsAdd(&Header->MenuList,pos,0);
  1353.         menu->Pointer = MidasCreateEmptyList("");
  1354.       }
  1355.     else
  1356.       {
  1357.         CustomBuildMenu(Header,w,menu->Pointer);
  1358.       }
  1359.  
  1360.     connect = MidasAddItemToListPos(&Header->ConnectList,entry,0);
  1361.     link = XtNew(Link);
  1362.     connect->Pointer = link;
  1363.     link->Widget = w;
  1364.     link->Header = Header;
  1365.     XtAddCallback(w,XmNdestroyCallback,CustomDisconnect,(XtPointer) connect);
  1366. }
  1367. void CustomPopup(name)
  1368.       char   *name;
  1369. {
  1370.     CustomHeader *Header;
  1371.     ListItem *item = MidasFindItemInList(&CustomHeaders,name);
  1372.  
  1373.     if (item == 0) return;
  1374.  
  1375.     Header = item->Pointer;
  1376.  
  1377.     if (Header->Fetched == 0)
  1378.       {
  1379.         int n = 0;
  1380.         Arg args[10];
  1381.         XtSetArg(args[n],XmNuserData , Header); n++;
  1382.         CustomHeaders.Selected = item;
  1383.         Header->Fetched = MidasFetch("Midas_Custom",Header->Parent);
  1384.         XtSetValues(Header->Fetched,args,n); 
  1385.       }
  1386.     if (XtIsManaged(Header->Fetched) == 0)
  1387.       {
  1388.         Header->TempVerbList = NullList;
  1389.         Header->TempMenuList = NullList;
  1390.         CustomCopyVerbList(&Header->VerbList,&Header->TempVerbList);
  1391.         CustomCopyMenuList(&Header->MenuList,&Header->TempMenuList);
  1392.         MidasRealizeList(&Header->TempVerbList,Header->CustomVerbList);
  1393.         MidasRealizeList(&Header->TempMenuList,Header->CustomMenuList);
  1394.         Header->Changed = 0;
  1395.         XtManageChild(Header->Fetched);
  1396.       }
  1397.     CustomUpdateSensitivity(Header);
  1398. }
  1399. void CustomCreate(name,parent)
  1400.       char   *name;
  1401.       Widget parent;
  1402. {
  1403.     CustomHeader *NewHeader;
  1404.     ListItem *NewItem;
  1405.  
  1406.     if (MidasFindItemInList(&CustomHeaders,name)) return;
  1407.  
  1408.     NewItem   =  MidasAddItemToList(&CustomHeaders,name);
  1409.  
  1410.     NewHeader = XtNew(CustomHeader);
  1411.     NewItem->Pointer = NewHeader;
  1412.  
  1413.     NewHeader->Modified     = 0;
  1414.     NewHeader->Fetched      = 0;
  1415.     NewHeader->Parent       = parent;
  1416.     NewHeader->MenuList     = NullList;
  1417.     NewHeader->VerbList     = NullList;
  1418.     NewHeader->TempMenuList = NullList;
  1419.     NewHeader->TempVerbList = NullList;
  1420.     NewHeader->VMList       = 0;
  1421.     NewHeader->ConnectList  = NullList;
  1422.     CustomRead(NewHeader,name,1);
  1423. }
  1424. int CustomExit()
  1425. {
  1426.     ListItem *i;
  1427.     int mods = 0;
  1428.     Widget w;
  1429.  
  1430.     for (i = CustomHeaders.First; i != 0; i = i->Next)
  1431.       {
  1432.         CustomHeader *Header = i->Pointer;
  1433.         mods += Header->Modified;
  1434.       }
  1435.  
  1436.     if (mods>0)
  1437.       {
  1438.         w = MidasFetch("MidasCustomExitDialog",0);
  1439.         XtManageChild(w);
  1440.         ExitResponse = -1;
  1441.         for (;ExitResponse == -1;) MidasFetchDispatchEvent();
  1442.       }
  1443.     if (ExitResponse == 2 )              /* Cancel */   
  1444.       {
  1445.         XtUnmanageChild(w);
  1446.         return 0;    
  1447.       }
  1448.     if (ExitResponse == 1 )              /* Yes    */
  1449.       for (i = CustomHeaders.First; i != 0; i = i->Next)
  1450.         {
  1451.           CustomHeader *Header = i->Pointer;
  1452.           if (Header->Modified != 0)
  1453.             CustomWrite(Header,i->Entry);
  1454.         }
  1455.     return 1;
  1456. }
  1457. static void CustomExitCallback(w,tag,cbDataP)
  1458.       Widget w; 
  1459.       int    *tag; 
  1460.       XmAnyCallbackStruct *cbDataP;
  1461. {
  1462.     ExitResponse = *tag;
  1463. }
  1464. void CustomInit()
  1465. {
  1466.     static MrmRegisterArg reglist[] = {
  1467.         {"CustomAddVerb",             (caddr_t)   CustomAddVerb},
  1468.         {"CustomDelVerb",             (caddr_t)   CustomDelVerb},
  1469.         {"CustomSelVerb",             (caddr_t)   CustomSelVerb},
  1470.         {"CustomSelConfVerb",         (caddr_t)   CustomSelConfVerb},
  1471.         {"CustomAddMenu",             (caddr_t)   CustomAddMenu},
  1472.         {"CustomDelMenu",             (caddr_t)   CustomDelMenu},
  1473.         {"CustomSelMenu",             (caddr_t)   CustomSelMenu},
  1474.         {"CustomSelConfMenu",         (caddr_t)   CustomSelConfMenu},
  1475.         {"CustomVMAddSeparator",      (caddr_t)   CustomVMAddSeparator},
  1476.         {"CustomVMAddVerb",           (caddr_t)   CustomVMAddVerb},
  1477.         {"CustomVMAddMenu",           (caddr_t)   CustomVMAddMenu},
  1478.         {"CustomVMDel",               (caddr_t)   CustomVMDel},
  1479.         {"CustomVMSel",               (caddr_t)   CustomVMSel},
  1480.         {"CustomVMSelConf",           (caddr_t)   CustomVMSelConf},
  1481.         {"CustomVMUp",                (caddr_t)   CustomVMUp},
  1482.         {"CustomVMDown",              (caddr_t)   CustomVMDown},
  1483.         {"CustomUpdateSensitivity",   (caddr_t)   CustomUpdateSensitivityCallback},
  1484.         {"CustomCreate",              (caddr_t)   CustomCreateCallback },
  1485.         {"CustomApply",               (caddr_t)   CustomApply },
  1486.         {"CustomReset",               (caddr_t)   CustomReset },
  1487.         {"CustomOk",                  (caddr_t)   CustomOk },
  1488.         {"CustomCancel",              (caddr_t)   CustomCancel },
  1489.         {"CustomExit",                (caddr_t)   CustomExitCallback }
  1490.     };
  1491.     MrmRegisterNames(reglist, XtNumber (reglist));
  1492.  
  1493.     CustomHeaders = NullList;
  1494.  
  1495.     MidasDeclareVerb("CUSTOM CREATE      upname Widget"     ,CustomCreate);
  1496.     MidasDeclareVerb("CUSTOM POPUP       upname"            ,CustomPopup);
  1497.     MidasDeclareVerb("CUSTOM CONNECT     upname name Widget",CustomConnect);
  1498.     MidasDeclareVerb("CUSTOM WRITE       upname {name}"     ,CustomWriteUser);
  1499.     MidasDeclareVerb("CUSTOM READ USER   upname {name}"     ,CustomReadUser);
  1500.     MidasDeclareVerb("CUSTOM READ SYSTEM upname {name}"     ,CustomReadSystem);
  1501. }
  1502.